package com.kingyea.mobilepolice.permission.service.impl;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.kingyea.mobilepolice.permission.bean.Permission;
import com.kingyea.mobilepolice.permission.bean.PermissionCondition;
import com.kingyea.mobilepolice.permission.bean.PermissionPo;
import com.kingyea.mobilepolice.permission.dao.PermissionMapper;
import com.kingyea.mobilepolice.permission.service.PermissionService;
import com.kingyea.mobilepolice.role.bean.Role;
import com.kingyea.mobilepolice.role.bean.RoleCondition;
import com.kingyea.mobilepolice.role.service.RoleService;
import com.kingyea.mobilepolice.rolepermission.bean.RolePermission;
import com.kingyea.mobilepolice.rolepermission.bean.RolePermissionCondition;
import com.kingyea.mobilepolice.rolepermission.dao.RolePermissionMapper;
import com.kingyea.mobilepolice.system.StateCode;
import com.kingyea.mobilepolice.util.ExceptionConditions;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.access.SecurityConfig;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

import static java.util.Comparator.comparingInt;
import static java.util.stream.Collectors.collectingAndThen;
import static java.util.stream.Collectors.toCollection;

/**
 * @author Mr.Lin
 * @version v1.0.0
 * @description Permission 实现类
 * @date Created in 2018-03-30 15:27:53
 */
@Service
@Transactional
public class PermissionServiceImpl implements PermissionService {

    private static final Logger LOGGER = LoggerFactory.getLogger(PermissionServiceImpl.class);

    @Resource
    private PermissionMapper permissionMapper;

    @Autowired
    private RolePermissionMapper rolePermissionMapper;

    @Autowired
    private RoleService roleService;

    /**
     * 通过ID查找对象
     *
     * @param id
     * @return
     */
    @Override
    public Permission getById(Integer id) {
        return this.permissionMapper.getById(id);
    }

    /**
     * 列表
     *
     * @param
     * @return
     */
    @Override
    public List<Permission> search(PermissionCondition condition) {
        List<Permission> list = permissionMapper.search(condition);
        condition.setList(list);
        return list;
    }

    /**
     * 删除
     *
     * @param id
     * @return
     */
    @Override
    public boolean deleteById(Integer id) throws Exception {
        Permission permission = permissionMapper.getById(id);
        return permissionMapper.update(permission) > 0;
    }

    /**
     * 保存
     *
     * @param permission
     * @return
     */
    @Override
    public Permission save(Permission permission) throws Exception {
        try {
            permissionMapper.save(permission);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return permission;
    }

    /**
     * 更新
     *
     * @param permission
     * @return
     */
    @Override
    public Permission update(Permission permission) throws Exception {
        try {
            permissionMapper.update(permission);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return permission;
    }

    /**
     * @Description: 封装spring security需要的对象类型
     * @Param: []
     * @return: java.util.Map<java.lang.String                                                                                                                                                                                                                                                               ,                                                                                                                                                                                                                                                               java.util.Collection                                                                                                                                                                                                                                                               <                                                                                                                                                                                                                                                               org.springframework.security.access.ConfigAttribute>>
     * @Author: cxc
     * @Date: 2018.04.03 14:10
     */
    @Override
    public Map<String, Collection<ConfigAttribute>> allPermissionRolesMap() {
        int pageSize = 10000;
        RolePermissionCondition rolePermissionCondition = new RolePermissionCondition();
        rolePermissionCondition.setPageSize(pageSize);
        List<RolePermission> rolePermissionList = rolePermissionMapper.search(rolePermissionCondition);

        RoleCondition roleCondition = new RoleCondition();
        roleCondition.setPageSize(pageSize);
        List<Role> roleList = roleService.search(roleCondition);

        HashMap<String, Collection<ConfigAttribute>> permissionRolesMap = Maps.newHashMap();

        PermissionCondition permissionCondition = new PermissionCondition();
        permissionCondition.setPageSize(pageSize);
        permissionMapper.search(permissionCondition).stream().forEach(permission -> {
            HashSet<Integer> roleIdSet = rolePermissionList.stream().filter(rolePermission -> rolePermission.getPermissionId().equals(permission.getId())).map(RolePermission::getRoleId).collect(Collectors.toCollection(HashSet::new));
            Collection<ConfigAttribute> roleNameSet = roleList.stream().filter(role -> roleIdSet.contains(role.getId())).map(role -> new SecurityConfig(role.getSerialNo().toUpperCase())).collect(Collectors.toCollection(HashSet::new));//roleName 全转大写
            permissionRolesMap.put(permission.getCode(), roleNameSet);
        });
        return permissionRolesMap;
    }

    public Collection<SimpleGrantedAuthority> allRoleAndPermissionByUserId(String userId) {
        List<Permission> permissionList = Lists.newArrayList();
        List<Role> roleList = roleService.searchByUserId(userId);
        if (roleList.size() > 0) {


            Set<Integer> roleIdSet = roleList.stream().map(Role::getId).collect(Collectors.toSet());

            RolePermissionCondition rolePermissionCondition = new RolePermissionCondition();
            rolePermissionCondition.setRoleIds(Lists.newArrayList(roleIdSet));
            rolePermissionCondition.setPageAble(false);
            List<RolePermission> rolePermissionList = rolePermissionMapper.search(rolePermissionCondition);

            if (rolePermissionList.size() > 0) {
                Set<Integer> permissionIdSet = rolePermissionList.stream().map(RolePermission::getPermissionId).collect(Collectors.toSet());
                PermissionCondition permissionCondition = new PermissionCondition();
                permissionCondition.setIds(Lists.newArrayList(permissionIdSet));
                permissionCondition.setPageAble(false);
                permissionList.addAll(permissionMapper.search(permissionCondition));
            }
        }
        HashSet<SimpleGrantedAuthority> authorCollection = permissionList.stream().map(permission -> new SimpleGrantedAuthority(permission.getCode())).collect(Collectors.toCollection(HashSet::new));
        authorCollection.addAll(roleList.stream().map(role -> new SimpleGrantedAuthority(role.getSerialNo())).collect(Collectors.toCollection(HashSet::new)));
        return authorCollection;
    }

    @Override
    public List<Permission> myPermissions(String userId) {
        List<Permission> permissionList = Lists.newArrayList();
        List<Role> roleList = roleService.searchByUserId(userId);
        if (roleList.size() > 0) {


            Set<Integer> roleIdSet = roleList.stream().map(Role::getId).collect(Collectors.toSet());

            RolePermissionCondition rolePermissionCondition = new RolePermissionCondition();
            rolePermissionCondition.setRoleIds(Lists.newArrayList(roleIdSet));
            rolePermissionCondition.setPageAble(false);
            List<RolePermission> rolePermissionList = rolePermissionMapper.search(rolePermissionCondition);

            if (rolePermissionList.size() > 0) {
                Set<Integer> permissionIdSet = rolePermissionList.stream().map(RolePermission::getPermissionId).collect(Collectors.toSet());
                PermissionCondition permissionCondition = new PermissionCondition();
                permissionCondition.setIds(Lists.newArrayList(permissionIdSet));
                permissionCondition.setPageAble(false);
                permissionList.addAll(permissionMapper.search(permissionCondition));
            }
        }
        return permissionList.stream().collect(collectingAndThen(toCollection(() -> new TreeSet<>(comparingInt(Permission::getId))), ArrayList::new));
    }

    @Transactional
    @Override
    public boolean addPermissionsForRoleId(PermissionPo po) {
        //校验数据格式
        ExceptionConditions.checkNotNull(po, StateCode.NO_ARGUMENT_ERROR);
        ExceptionConditions.checkNotNull(po.getRoleId(), StateCode.NO_ARGUMENT_ERROR);
        ExceptionConditions.checkNotNull(po.getPermissionIds(), StateCode.NO_ARGUMENT_ERROR);

        rolePermissionMapper.deleteByRoleId(po.getRoleId());

        Integer i = 0;
        for (Integer permisstionId : po.getPermissionIds()) {
            RolePermission rolePermission = new RolePermission();
            rolePermission.setRoleId(po.getRoleId());
            rolePermission.setPermissionId(permisstionId);
            rolePermission.setLastUpdatedDate(new Date());
            rolePermission.setCreatedDate(new Date());
            ExceptionConditions.checkArgument(rolePermissionMapper.save(rolePermission) == 1, StateCode.SYSTEM_ERROR);
            i++;
        }
        return i.equals(po.getPermissionIds().size());
    }

    @Transactional
    @Override
    public boolean delPermissionsForRoleId(PermissionPo po) {
        ExceptionConditions.checkNotNull(po, StateCode.NO_ARGUMENT_ERROR);
        ExceptionConditions.checkNotNull(po.getRoleId(), StateCode.NO_ARGUMENT_ERROR);
        rolePermissionMapper.deleteByRoleId(po.getRoleId());
        return true;
    }

    @Override
    public List<Permission> searchByRoleId(Integer roleId) {
        ExceptionConditions.checkNotNull(roleId, StateCode.NO_ARGUMENT_ERROR);
        RolePermissionCondition rolePermissionCondition = new RolePermissionCondition();
        rolePermissionCondition.setRoleId(roleId);
        rolePermissionCondition.setPageAble(false);
        Set<Integer> permissionIdSet = rolePermissionMapper.search(rolePermissionCondition).stream().map(RolePermission::getPermissionId).collect(Collectors.toSet());
        if (permissionIdSet.isEmpty()) {
            return Lists.newArrayList();
        }
        PermissionCondition permissionCondition = new PermissionCondition();
        permissionCondition.setIds(Lists.newArrayList(permissionIdSet));
        permissionCondition.setPageAble(false);
        return permissionMapper.search(permissionCondition);
    }

}
